home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 03 - 1987 / 03.05 May 87 / c source / abc 9 source code / dr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-04-08  |  10.9 KB  |  683 lines  |  [TEXT/KAHL]

  1. /* 
  2.  * dr.c
  3.  *
  4.  * drawing routines
  5.  */
  6.  
  7.  #include    "abc.h"
  8.  #include    "quickdraw.h"
  9.  #include    "windowMgr.h"
  10.  
  11. struct shapes
  12.     {
  13.     short    kind;
  14.     Rect    size;
  15.     short    oper;
  16.     };
  17.             
  18.  
  19. struct shapes   shapa[20];
  20. short                        shapdx;
  21. PolyHandle            triangle;
  22. PolyHandle            pentagon;
  23. PolyHandle            hexagon;
  24. PolyHandle            pentagram;
  25. RgnHandle                theregion;
  26. RgnHandle                tempregion;
  27.  
  28. PolyHandle            polytemp = 0;
  29. PolyHandle            polycurrent;
  30. short                        phpts;
  31.  
  32.  
  33. /*
  34.  * Quickdraw surround functions.
  35.  * These functions provide a consistent 
  36.  * interface (at some loss of generality) to
  37.  * all the quickdraw drawing functions.
  38.  */
  39.  
  40.  /* FRAMING */
  41.  
  42. fr_poly(startpt,endpt)
  43.     Point    startpt, endpt;
  44. {
  45.     Rect        drt;
  46.     Rect        srt;
  47.     
  48.     Pt2Rect(startpt,endpt,&drt);
  49.     BlockMove(&(*polycurrent)->polyBBox, &srt,sizeof(Rect));
  50.     BlockMove(*polycurrent,*polytemp,(*polycurrent)->polySize);
  51.     InsetRect(&srt, -1, -1);
  52.     MapPoly(polytemp,&srt, &drt);
  53.     FramePoly(polytemp);
  54. }
  55.     
  56. fr_regn(startpt, endpt)
  57.     Point    startpt, endpt;
  58. {
  59.     Rect        r, r1;
  60.     
  61.     CopyRgn(theregion,tempregion);
  62.     BlockMove(&(*tempregion)->rgnBBox, &r1,sizeof(Rect));
  63.     InsetRect(&r1,-1,-1);
  64.     Pt2Rect(startpt, endpt,&r);
  65.     MapRgn(tempregion, &r1, &r);
  66.     FrameRgn(tempregion);
  67. }
  68.  
  69. fr_line(startpt,endpt)
  70.     Point    startpt,endpt;
  71. {
  72.     MoveTo(startpt.h,startpt.v);
  73.     LineTo(endpt.h,endpt.v);
  74. }
  75.  
  76. fr_rect(startpt,endpt)
  77.     Point    startpt,endpt;
  78. {
  79.     Rect    rt;
  80.     
  81.     Pt2Rect(startpt,endpt,&rt);
  82.     FrameRect(&rt);
  83. }
  84.  
  85. fr_oval(startpt,endpt)
  86.     Point    startpt,endpt;
  87. {
  88.     Rect    rt;
  89.     
  90.     Pt2Rect(startpt,endpt,&rt);
  91.     FrameOval(&rt);
  92. }
  93.  
  94. fr_rort(startpt,endpt)
  95.     Point    startpt,endpt;
  96. {
  97.     Rect    rt;
  98.     
  99.     Pt2Rect(startpt,endpt,&rt);
  100.     FrameRoundRect(&rt,20,20);
  101. }
  102.  
  103.  
  104. fr_arc(startpt,endpt)
  105.     Point    startpt,endpt;
  106. {
  107.     Rect    rt;
  108.     Rect    trt;
  109.     short    sa;
  110.     short    aa;
  111.     
  112.     Pt2Rect(startpt,endpt,&rt);
  113.     cp_arc(&rt,&trt,&sa,&aa);
  114.     FrameArc (&trt,sa,aa);
  115. }
  116.  
  117. /* ERASING */
  118.  
  119. er_line(startpt,endpt)
  120.     Point    startpt,endpt;
  121. {
  122.     GrafPtr        gp;
  123.     Pattern        tpat;
  124.     
  125.     GetPort(&gp);
  126.     BlockMove(gp->pnPat,&tpat,8);
  127.     PenPat(gp->bkPat);
  128.     MoveTo(startpt.h,startpt.v);
  129.     LineTo(endpt.h,endpt.v);
  130.     PenPat(&tpat);
  131. }
  132.  
  133. er_poly(startpt,endpt)
  134.     Point    startpt, endpt;
  135. {
  136.     Rect        drt;
  137.     Rect        srt;
  138.     
  139.     Pt2Rect(startpt,endpt,&drt);
  140.     BlockMove(*polycurrent,*polytemp,(*polycurrent)->polySize);
  141.     BlockMove(&(*polycurrent)->polyBBox,&srt,sizeof(Rect));
  142.     InsetRect(&srt, -1, -1);
  143.     MapPoly(polytemp,&srt,&drt);
  144.     ErasePoly(polytemp);
  145. }
  146.  
  147. er_regn(startpt, endpt)
  148.     Point    startpt, endpt;
  149. {
  150.     Rect        r, r1;
  151.     
  152.     CopyRgn(theregion,tempregion);
  153.     BlockMove(&(*tempregion)->rgnBBox, &r1,sizeof(Rect));
  154.     InsetRect(&r1,-1,-1);
  155.     Pt2Rect(startpt, endpt,&r);
  156.     MapRgn(tempregion, &r1, &r);
  157.     EraseRgn(tempregion);
  158. }
  159.  
  160.  
  161. er_rect(startpt,endpt)
  162.     Point    startpt,endpt;
  163. {
  164.     Rect    rt;
  165.     
  166.     Pt2Rect(startpt,endpt,&rt);
  167.     EraseRect(&rt);
  168. }
  169.  
  170. er_oval(startpt,endpt)
  171.     Point    startpt,endpt;
  172. {
  173.     Rect    rt;
  174.     
  175.     Pt2Rect(startpt,endpt,&rt);
  176.     EraseOval(&rt);
  177. }
  178.  
  179. er_rort(startpt,endpt)
  180.     Point    startpt,endpt;
  181. {
  182.     Rect    rt;
  183.     
  184.     Pt2Rect(startpt,endpt,&rt);
  185.     EraseRoundRect(&rt,20,20);
  186. }
  187.  
  188. er_arc(startpt,endpt)
  189.     Point    startpt,endpt;
  190. {
  191.     Rect    rt;
  192.     Rect    trt;
  193.     short    sa;
  194.     short    aa;
  195.     
  196.     Pt2Rect(startpt,endpt,&rt);
  197.     cp_arc(&rt,&trt,&sa,&aa);
  198.     EraseArc (&trt,sa,aa);
  199. }
  200.  
  201. /* PAINTING */
  202.  
  203. pt_line(startpt,endpt)
  204.     Point    startpt,endpt;
  205. {
  206.     GrafPtr        gp;
  207.     Pattern        tpat;
  208.     
  209.     MoveTo(startpt.h,startpt.v);
  210.     LineTo(endpt.h,endpt.v);
  211. }
  212.  
  213. pt_poly(startpt,endpt)
  214.     Point    startpt, endpt;
  215. {
  216.     Rect        drt;
  217.     Rect        srt;
  218.     
  219.     Pt2Rect(startpt,endpt,&drt);
  220.     BlockMove(*polycurrent,*polytemp,(*polycurrent)->polySize);
  221.     BlockMove(&(*polycurrent)->polyBBox,&srt,sizeof(Rect));
  222.     InsetRect(&srt, -1, -1);
  223.     MapPoly(polytemp,&srt,&drt);
  224.     PaintPoly(polytemp);
  225. }
  226.  
  227. pt_regn(startpt, endpt)
  228.     Point    startpt, endpt;
  229. {
  230.     Rect        r, r1;
  231.     
  232.     CopyRgn(theregion,tempregion);
  233.     BlockMove(&(*tempregion)->rgnBBox, &r1,sizeof(Rect));
  234.     InsetRect(&r1,-1,-1);
  235.     Pt2Rect(startpt, endpt,&r);
  236.     MapRgn(tempregion, &r1, &r);
  237.     PaintRgn(tempregion);
  238. }
  239.  
  240. pt_rect(startpt,endpt)
  241.     Point    startpt,endpt;
  242. {
  243.     Rect    rt;
  244.     
  245.     Pt2Rect(startpt,endpt,&rt);
  246.     PaintRect(&rt);
  247. }
  248.  
  249. pt_oval(startpt,endpt)
  250.     Point    startpt,endpt;
  251. {
  252.     Rect    rt;
  253.     
  254.     Pt2Rect(startpt,endpt,&rt);
  255.     PaintOval(&rt);
  256. }
  257.  
  258. pt_rort(startpt,endpt)
  259.     Point    startpt,endpt;
  260. {
  261.     Rect    rt;
  262.     
  263.     Pt2Rect(startpt,endpt,&rt);
  264.     PaintRoundRect(&rt,20,20);
  265. }
  266.  
  267.  
  268. pt_arc(startpt,endpt)
  269.     Point    startpt,endpt;
  270. {
  271.     Rect    rt;
  272.     Rect    trt;
  273.     short    sa;
  274.     short    aa;
  275.     
  276.     Pt2Rect(startpt,endpt,&rt);
  277.     cp_arc(&rt,&trt,&sa,&aa);
  278.     PaintArc (&trt,sa,aa);
  279. }
  280.  
  281. /* INVERTING */
  282.  
  283. in_line(startpt,endpt)
  284.     Point    startpt,endpt;
  285. {
  286.     GrafPtr        gp;
  287.     short        tpnMode;
  288.     
  289.     GetPort(&gp);
  290.     tpnMode = gp->pnMode;
  291.     PenMode(patXor);
  292.     MoveTo(startpt.h,startpt.v);
  293.     LineTo(endpt.h,endpt.v);
  294.     PenMode(tpnMode);
  295. }
  296.  
  297. in_rect(startpt,endpt)
  298.     Point    startpt,endpt;
  299. {
  300.     Rect    rt;
  301.     
  302.     Pt2Rect(startpt,endpt,&rt);
  303.     InvertRect(&rt);
  304. }
  305.  
  306. in_poly(startpt,endpt)
  307.     Point    startpt, endpt;
  308. {
  309.     Rect        drt;
  310.     Rect        srt;
  311.     
  312.     Pt2Rect(startpt,endpt,&drt);
  313.     BlockMove(*polycurrent,*polytemp,(*polycurrent)->polySize);
  314.     srt=(*polytemp)->polyBBox;
  315.     InsetRect(&srt,1,1);
  316.     MapPoly(polytemp,&srt,&drt);
  317.     InvertPoly(polytemp);
  318. }
  319.  
  320. in_regn(startpt, endpt)
  321.     Point    startpt, endpt;
  322. {
  323.     Rect        r, r1;
  324.     
  325.     CopyRgn(theregion,tempregion);
  326.     BlockMove(&(*tempregion)->rgnBBox, &r1,sizeof(Rect));
  327.     InsetRect(&r1,-1,-1);
  328.     Pt2Rect(startpt, endpt,&r);
  329.     MapRgn(tempregion, &r1, &r);
  330.     InvertRgn(tempregion);
  331. }
  332.  
  333. in_oval(startpt,endpt)
  334.     Point    startpt,endpt;
  335. {
  336.     Rect    rt;
  337.     
  338.     Pt2Rect(startpt,endpt,&rt);
  339.     InvertOval(&rt);
  340. }
  341.  
  342. in_rort(startpt,endpt)
  343.     Point    startpt,endpt;
  344. {
  345.     Rect    rt;
  346.     
  347.     Pt2Rect(startpt,endpt,&rt);
  348.     InvertRoundRect(&rt,20,20);
  349. }
  350.  
  351. in_arc(startpt,endpt)
  352.     Point    startpt,endpt;
  353. {
  354.     Rect    rt;
  355.     Rect    trt;
  356.     short    sa;
  357.     short    aa;
  358.     
  359.     Pt2Rect(startpt,endpt,&rt);
  360.     cp_arc(&rt,&trt,&sa,&aa);
  361.     InvertArc (&trt,sa,aa);
  362. }
  363.  
  364. /* SURROUND FUNCTION SUPPORT */
  365.  
  366.  
  367. /* ARC COMPUTATION
  368.  * The arc is fixed at 90 degrees. This
  369.  * function (used in all the arc functions
  370.  * above) computes the correct rectangle, 
  371.  * start angle, and arc angle given the
  372.  * input rectangle (and 90 degrees).
  373.  *
  374.  * This makes drawing the arcs consistent
  375.  * with drawing the other shapes.
  376.  */
  377. cp_arc(irt,ort,startangle,arcangle)
  378.     Rect    *irt;
  379.     Rect    *ort;
  380.     short    *startangle;
  381.     short    *arcangle;
  382. {
  383.     short    dh;
  384.     short    dv;
  385.     static Point    anchor;
  386.     
  387.     dh = irt->right - irt->left;
  388.     dv = irt->bottom - irt->top;
  389.     if (not (dh | dv))
  390.         {
  391.         anchor.v = irt->top;
  392.         anchor.h = irt->left;
  393.         }
  394.     *ort = *irt;
  395.     
  396.     if (irt->left equals anchor.h)
  397.         if (irt->top < anchor.v)
  398.             {
  399.             ort->left -= dh;
  400.             ort->top -= dv;
  401.             *startangle = 180;
  402.             *arcangle = -90;
  403.             }
  404.         else
  405.             {
  406.             ort->left -= dh;
  407.             ort->bottom += dv;
  408.             *startangle = 0;
  409.             *arcangle = 90;
  410.             }
  411.     else
  412.         if (irt->top < anchor.v)
  413.             {
  414.             ort->top -= dv;
  415.             ort->right += dh;
  416.             *startangle = 180;
  417.             *arcangle = 90;
  418.             }
  419.         else
  420.             {
  421.             ort->right += dh;
  422.             ort->bottom += dv;
  423.             *startangle = 0;
  424.             *arcangle = - 90;
  425.             }
  426. }
  427.  
  428.     
  429. typedef    short    (*drfunc)();
  430.  
  431. drfunc    a[][7] = 
  432.                          {fr_line,fr_rect,fr_oval,fr_rort,fr_arc,fr_poly,fr_regn,
  433.                           pt_line,pt_rect,pt_oval,pt_rort,pt_arc,pt_poly,pt_regn,
  434.                           er_line,er_rect,er_oval,er_rort,er_arc,er_poly,er_regn,
  435.                           in_line,in_rect,in_oval,in_rort,in_arc,in_poly,in_regn};
  436.  
  437. /* INITIALIZE DRAWING
  438.  * Init all kinds in shape array (not used
  439.  * yet and make polygons
  440.  */
  441.  
  442. drinit()
  443. {
  444.     short    i;
  445.     
  446.     for (i = 0; i < 20; shapa[i++].kind = 0);
  447.     
  448.     shapdx = 0;
  449.     maketriangle();
  450.     makepentagon();
  451.     makehexagon();
  452.     makepentagram();
  453.     makeregion();
  454. }
  455.  
  456. /* SET SHAPE
  457.  * This sets the shape code to use
  458.  *  and sets it in the current shape
  459.  *  entry (only one is used so far).
  460.  * In the case of polygons, it translates
  461.  *  the shape code to the polygon code and
  462.  *  sets the polygon to use in the
  463.  *  global, polycurrent.
  464.  */
  465. drshape(code)
  466.     short    code;
  467. {
  468.     switch (code)
  469.         {
  470.         case 6: 
  471.             polycurrent = triangle;
  472.             break;
  473.         case 7:
  474.             polycurrent = pentagon;
  475.             code = 6;
  476.             break;
  477.         case 8:
  478.             polycurrent = hexagon;
  479.             code = 6;
  480.             break;
  481.         case 9:
  482.             polycurrent = pentagram;
  483.             code = 6;
  484.             break;
  485.         case 10:
  486.             code = 7;
  487.             break;
  488.         }
  489.     shapa[shapdx].kind = code;
  490. }
  491.  
  492. /* SET OPERATION
  493.  * Sets operation in shape array
  494.  *  (only one used).  Also sets
  495.  *  cursor to use.
  496.  */
  497.  
  498. droper(code)
  499.     short    code;
  500. {
  501.     shapa[shapdx].oper = code;
  502.     CursorToUse(2);
  503. }
  504.  
  505. drdraw(w)
  506.     WindowRecord    *w;
  507. {
  508.     Point                startpt;
  509.     Point                thispt;
  510.     Point                endpt;
  511.     Point                lastpt;
  512.     Rect                thisrt;
  513.     Rect                lastrt;
  514.     GrafPtr            port;
  515.     drfunc            frame;
  516.     drfunc            draw;
  517.     short                angle;
  518.     short                dv,dh;
  519.     Point                sp;
  520.     Point                tp;
  521.     Point                lp;
  522.     short                shapx;
  523.     short                operx;
  524.     short                x;
  525.     short                y;
  526.     
  527.     SetPort((GrafPtr)w);
  528.     PenMode(patXor);
  529.     PenPat(gray);
  530.     shapx = shapa[shapdx].kind - 1;
  531.     operx = shapa[shapdx].oper - 1;
  532.     if ((shapx < 0) or (operx < 0)) 
  533.         return;                                                
  534.     frame = a[0][shapx];                /* get address of frame func */
  535.     draw  = a[operx][shapx];        /* get address of shape/oper func */
  536.     
  537.     GetMouse(&startpt);
  538.     x=startpt.h;
  539.     y=startpt.v;
  540.     if (x%2 notequal 0)
  541.         x=x+1;
  542.     if (y%2 notequal 0)
  543.         y=y+1;
  544.     startpt.h=x;
  545.     startpt.v=y;
  546.     lastpt=startpt;
  547.     
  548.     do    {
  549.         GetMouse(&endpt);
  550.         
  551.                 x=endpt.h;
  552.                 y=endpt.v;
  553.                 if (x%2 notequal 0)
  554.                     x=x+1;
  555.                 if (y%2 notequal 0)
  556.                     y=y+1;
  557.                 endpt.h=x;
  558.                 endpt.v=y;
  559.                 
  560.         thispt = endpt;
  561.         LocalToGlobal(&endpt);
  562.         if (PtInRgn(endpt,w->contRgn) and 
  563.             not EqualPt(thispt,lastpt))
  564.             {
  565.             if (not EqualPt(startpt,lastpt))
  566.                 (*frame)(startpt,lastpt);
  567.             (*frame)(startpt,thispt);
  568.             lastpt = thispt;
  569.             }
  570.         }
  571.     while (StillDown());
  572.     
  573.     (*frame)(startpt,thispt);
  574.     PenMode(patCopy);
  575.     PenPat(black);
  576.     (*draw)(startpt,thispt);    
  577. }
  578.  
  579. /*
  580.  * Make New Shapes 
  581.  *  These routines define polygons that
  582.  *  are available from the menu.  Each 
  583.  *  simply defines a polygon (assigning
  584.  *  it to the global variable of the
  585.  *  appropriate name).
  586.  *     NO ERROR CHECKING IS DONE ON THE
  587.  *    MEMORY OPERATIONS.
  588.  */
  589.  
  590. maketriangle()
  591. {
  592.     short    err;
  593.     
  594.     triangle = OpenPoly();
  595.     MoveTo(20,20);
  596.     Line(20,0);
  597.     Line(-10,-20);
  598.     Line(-10,20);
  599.     ClosePoly();
  600.     setpolytemp((*triangle)->polySize);
  601. }
  602.  
  603. makepentagon()
  604. {
  605.     pentagon = OpenPoly();
  606.     MoveTo(50,0);
  607.     Line(48,35);
  608.     Line(-19,65);
  609.     Line(-58,0);
  610.     Line(-19,-65);
  611.     Line(48,-35);
  612.     ClosePoly();
  613.     setpolytemp((*pentagon)->polySize);
  614. }
  615.  
  616. makehexagon()
  617. {
  618.     hexagon = OpenPoly();
  619.     MoveTo (21,0);
  620.     Line(58,0);
  621.     Line(28,50);
  622.     Line(-28,50);
  623.     Line(-58,0);
  624.     Line(-28,-50);
  625.     Line(28,-50);
  626.     ClosePoly();
  627.     setpolytemp((*hexagon)->polySize);
  628. }
  629.  
  630. makepentagram()
  631. {
  632.     pentagram = OpenPoly();
  633.     MoveTo(50,0);
  634.     Line(30,90);
  635.     Line(-78,-55);
  636.     Line(96,0);
  637.     Line(-78,55);
  638.     Line(30,-90);
  639.     ClosePoly();
  640.     setpolytemp((*pentagram)->polySize);
  641. }
  642.  
  643. /* The original of the polygon is not 
  644.  *  changed when it is scaled and 
  645.  *  displayed.  Instead a copy is used.
  646.  *  Since the program has no idea how
  647.  *  big a space to reserve for the copy, 
  648.  *  setpolytemp() adjusts the size 
  649.  *  reserved for the global handle
  650.  *  polytemp.
  651.  *    NO ERROR CHECKING IS DONE ON THE 
  652.  *    MEMORY OPERATIONS.
  653.  */
  654. setpolytemp(size)
  655.     short    size;
  656. {
  657.     if (polytemp equals 0) 
  658.         polytemp = (PolyHandle)NewHandle(size);
  659.     else if (size > GetHandleSize(polytemp))
  660.         SetHandleSize(polytemp,size);
  661.     
  662. makeregion()
  663. {
  664.     Point        sp,ep;
  665.     Rect        r;
  666.     
  667.     sp.h = 10;
  668.     sp.v = 10;
  669.     ep.h = 60;
  670.     ep.v = 60;
  671.     theregion = NewRgn();
  672.     OpenRgn();
  673.     SetRect(&r,0,0,10,60);
  674.     FrameRect(&r);
  675.     SetRect(&r,40,0,50,60);
  676.     FrameRect(&r);
  677.     SetRect(&r,10,25,40,35);
  678.     FrameRect(&r);
  679.     CloseRgn(theregion);
  680.     tempregion = NewRgn();
  681. }
  682.